<?php

namespace App\Services;

use App\Enums\ReceptionType;
use App\Helpers\KeyHandler;
use App\Models\Reception;
use App\Models\ReceptionLog;
use App\Models\User;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Str;

class ReceptionService
{

    //接待类型
    public int $reception_type;
    //操作队列时候的原子锁
    public string $reception_cache_lock_key;

    //对接人缓存key
    public string $reception_user_cache_key;

    //优先对接人缓存key
    public string $priority_reception_user_cache_key;


    public function __construct(int $reception_type)
    {
        $this->reception_type = $reception_type;
        $this->reception_user_cache_key = sprintf(KeyHandler::RECEPTION_USER, Str::lower(ReceptionType::getKey($this->reception_type)));
        $this->priority_reception_user_cache_key = sprintf(KeyHandler::PRIORITY_RECEPTION_USER, Str::lower(ReceptionType::getKey($this->reception_type)));
        //原子锁
        $this->reception_cache_lock_key = sprintf(KeyHandler::RECEPTION_CACHE_LOCK, Str::lower(ReceptionType::getKey($this->reception_type)));

    }


    //更新接收人队列缓存
    public function updateReceptionUserCache()
    {
        //接待人
        $users = Reception::query()
            ->where('status', true)
            ->where('type', $this->reception_type)
            ->whereRaw('today_number < daily_number')
            ->get();
        if (count($users)) {
            $data = [];
            foreach ($users as $value) {
                $data = array_merge($data, array_fill(0, $value->weight ?: 1, $value->user_id));
            }
            shuffle($data);
            //存储到记录中去
            ReceptionLog::query()->create([
                'type' => $this->reception_type,
                'user_ids' => json_encode($data),
                'user_name' => join('|', User::query()->whereIn('id', $data)->orderByRaw("FIELD(id, " . implode(",", $data) . ")")->pluck('name')->toArray())
            ]);
            Redis::command('rpush', array_merge([$this->reception_user_cache_key], $data));
        }
    }

    //获取优先接待人
    public function getPriorityReceptionUser()
    {
        if (Redis::command('exists', [$this->priority_reception_user_cache_key])) {
            return Redis::command('lpop', [$this->priority_reception_user_cache_key]);
        }
        return 0;
    }


    //获取接待人
    public function getReceptionUser()
    {
        return Cache::lock($this->reception_cache_lock_key, 10)->get(function () {
            while (true) {
                $user_id = $this->getPriorityReceptionUser();
                if (!$user_id) {
                    if (!Redis::command('exists', [$this->reception_user_cache_key])) {
                        $this->updateReceptionUserCache();
                    }
                    $user_id = Redis::command('lpop', [$this->reception_user_cache_key]);
                }
                if (!$user_id) {
                    break;
                }
                //判断当前接待人是否合法(接待人被关闭或者删除，接待员工离职)
                $reception = Reception::query()
                    ->where('status', true)
                    ->where('type', $this->reception_type)
                    ->where('user_id', $user_id)
                    ->first();
                if ($reception && $reception->today_number < $reception->daily_number &&
                    User::query()->where('status', true)->where('id', $user_id)->exists()) {
                    //判断是否完了，完了就更新
                    if (!Redis::command('exists', [$this->reception_user_cache_key])) {
                        $this->updateReceptionUserCache();
                    }
                    break;
                }
            }
            return $user_id;
        });

    }


    //获取接待人列表
    public function getReceptionUserList(string $cache_key): string
    {
        $reception_user = Redis::command('lrange', [$cache_key, 0, -1]);
        if (!count($reception_user)) {
            return '暂无';
        }
        $users = User::query()->whereIn('id', $reception_user)->select(['id', 'name'])->get();
        $str = '';
        foreach ($reception_user as $user_id) {
            $str .= $users->where('id', $user_id)->first()->name . '|';
        }
        return rtrim($str, '|');
    }
}
